/**
  ETFDAQ Project
  \class TAGDAQ
  \brief The graphical user interface for the DAQ application
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-08-20
  \date 2024-08-20 last modified

  \copyright Copyright (c) 2024 IMP-CAS with LGPLv3 LICENSE
*/

#include <iostream>
#include <unistd.h>
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
#include <QLineEdit>
#include <QMenuBar>
#include <QLabel>
#include "TAGDAQ.h"
#include "TADAQ.h"
#include "TADAQThread.h"
#include "TAMsg.h"

using std::cout;
using std::endl;
using std::flush;
using std::string;

TAGDAQ::TAGDAQ(const string &dev, QWidget *parent) : QMainWindow(parent),
fDaqSta(EDAQSTA::UDF){
  resize(600, 600);
  setWindowTitle("ETFDAQ GUI");
  fMenuBar = menuBar();
  auto menu_file = fMenuBar->addMenu("&File");
  auto exit_acn = menu_file->addAction("E&xit");
  connect(exit_acn, &QAction::triggered, this, &TAGDAQ::exit);
  auto about_acn = menu_file->addAction("&About...");
  fAboutDiag = new QMessageBox(this);
  fAboutDiag->resize(250, 100);
  fAboutDiag->setInformativeText(
    "<p style='text-align: center;'><strong>ETFDAQ</strong></p>"
    "<p style='text-align: center;'>&nbsp;</p>"
    "<p style='text-align: center;'>Version 0.1.0 Aug. 26, 2024</p>"
    "<p style='text-align: center;'>by ASIA SUN asia.rabbit@163.com</p>"
    "<p style='text-align: center;'><a href=https://gitee.com/asiarabbit/etfdaq>"
    "https://gitee.com/asiarabbit/etfdaq</a></p>"
    "<p style='text-align: center;'>Copyright &copy; 2024 IMP-CAS with LGPLv3 LICENSE</p>"
  );
  fAboutDiag->setStandardButtons(QMessageBox::Ok);
  fAboutDiag->setDefaultButton(QMessageBox::Ok);
  connect(about_acn, &QAction::triggered, fAboutDiag, &QMessageBox::exec);

  fInit = new QPushButton("&Init", this);
  fStart = new QPushButton("St&art", this);
  fPause = new QPushButton("Pa&use", this);
  fResume = new QPushButton("&Resume", this);
  fStop = new QPushButton("&Stop", this);
  fStop->setStyleSheet("QPushButton{ background-color: cyan; }");
  fExit = new QPushButton("E&xit", this);
  fExit->setStyleSheet("QPushButton{ background-color: magenta; }");

  fStart->setDisabled(true);
  fPause->setDisabled(true);
  fResume->setDisabled(true);
  fStop->setDisabled(true);

  fInit->setToolTip("init and config the hardwares for daq");
  fStart->setToolTip("open data file and start daq");
  fPause->setToolTip("disable the trigger");
  fResume->setToolTip("recover the trigger");
  fStop->setToolTip("stop the daq and cloes the data file");
  fExit->setToolTip("save file (if any) and exit the program");

  fInit->move(0, 50); fExit->move(120, 50);
  fStart->move(0, 100);
  fStop->move(0, 150);
  fPause->move(0, 200);
  fResume->move(0, 250);

  fStartComment = new QLineEdit(this);
  fStopComment = new QLineEdit(this);
  fStartComment->setPlaceholderText("Please Enter header comment");
  fStopComment->setPlaceholderText("Please Enter trailer comment");
  fStartComment->setGeometry(100, 100, 400, 30); // (x, y, w, h)
  fStopComment->setGeometry(100, 150, 400, 30);
  fStartComment->setToolTip("the comment will be written on the head of the data file");
  fStopComment->setToolTip("the comment will be written on the tail of the data file");

  connect(fInit, &QPushButton::clicked, this, &TAGDAQ::init);
  connect(fStart, &QPushButton::clicked, this, &TAGDAQ::start);
  connect(fPause, &QPushButton::clicked, this, &TAGDAQ::pause);
  connect(fResume, &QPushButton::clicked, this, &TAGDAQ::resume);
  connect(fStop, &QPushButton::clicked, this, &TAGDAQ::stop);
  connect(fExit, &QPushButton::clicked, this, &TAGDAQ::exit);

  fDAQInfo = new QLabel("DAQ Info: To Be Initialized", this);
  fDAQState = new QLabel("DAQ State: Ready\n", this);
  fDAQInfo->setGeometry(0, 300, 500, 200);
  fDAQState->setGeometry(0, 520, 500, 50);
  fDAQInfo->setFont(QFont("Titillium Web", -1, QFont::Bold));
  fDAQState->setFont(QFont("Titillium Web", 15, QFont::Bold));

  fDAQThread = new TADAQThread(this, new TADAQ(dev));
  connect(this, &TAGDAQ::statusChanged, fDAQThread, &TADAQThread::updateStatus);
} // end ctor

TAGDAQ::~TAGDAQ(){}

void TAGDAQ::run(){
  show();
  emit fInit->clicked(); usleep(500000); // automatic init
  // emit fStart->clicked(); usleep(500000); // automatic start
} // end member function run

void TAGDAQ::init(){
  fMutex.lock();
  fInit->setDisabled(true);
  fDAQThread->start();
  fDaqSta = EDAQSTA::INIT;
  emit statusChanged(fDaqSta);
  fDAQInfo->setText("DAQInfo: the cards are initing...");
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#b8860b\">INITIALIZING... Please Wait...</span>"
    "</strong>");
  cout << "Init" << endl;
} // end member function init

// update to inited state
void TAGDAQ::inited(){
  fInit->setDisabled(true);
  fStart->setDisabled(false);
  fPause->setDisabled(true);
  fResume->setDisabled(true);
  fStop->setDisabled(true);
  cout << "Inited" << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#0000ff\">INITIALIZED</span>"
    "</strong>");

  fDAQInfo->setText("DAQInfo: To Be Started");
  fMutex.unlock();
} // end member funcition init

void TAGDAQ::start(){
  fMutex.lock();
  fDaqSta = EDAQSTA::START;
  emit statusChanged(fDaqSta);
  fStart->setDisabled(true);
  fPause->setDisabled(false);
  fResume->setDisabled(true);
  fStop->setDisabled(false);
  cout << "The DAQ has started" << endl;
  cout << "User Comment: " << fStartComment->text().toStdString() << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#00ff00\">RUNNING</span>"
    "</strong>");
} // end member funcition start

void TAGDAQ::pause(){
  fMutex.lock();
  fDaqSta = EDAQSTA::PAUSE;
  emit statusChanged(fDaqSta);
  fStart->setDisabled(true);
  fPause->setDisabled(true);
  fResume->setDisabled(false);
  fStop->setDisabled(false);
  cout << "Pause" << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#ff00ff\">PAUSED</span>"
    "</strong>");
} // end member funcition pause

void TAGDAQ::resume(){
  fMutex.lock();
  fDaqSta = EDAQSTA::RESUME;
  emit statusChanged(fDaqSta);
  fStart->setDisabled(true);
  fPause->setDisabled(false);
  fResume->setDisabled(true);
  fStop->setDisabled(false);
  cout << "Resume" << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#00ff00\">RUNNING</span>"
    "</strong>");
} // end member funcition resume

void TAGDAQ::stop(){
  fMutex.lock();
  fDaqSta = EDAQSTA::STOP;
  emit statusChanged(fDaqSta);
  fStart->setDisabled(true);
  fPause->setDisabled(false);
  fResume->setDisabled(true);
  fStop->setDisabled(false);
  cout << "Stop" << endl;
  cout << "User Comment: " << fStopComment->text().toStdString() << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#ff0000\">STOPPED</span>"
    "</strong>");
} // end member funcition stop

void TAGDAQ::exit(){
  fMutex.lock();
  fDaqSta = EDAQSTA::EXIT;
  emit statusChanged(fDaqSta);
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#ff0000\">EXITING</span>"
    "</strong>");
  if(fDAQThread->isRunning()){
    fDAQThread->quit();
    fDAQThread->wait();
  } // end if
  TAMsg::Logo();
  cout << "\033[32;1m\nBye~\033[0m" << endl;
  QApplication::quit();
} // end member funcition exit

void TAGDAQ::updateDAQInfo(const QString &m){
  fDAQInfo->setText(m);
} // end member function updateDAQInfo

void TAGDAQ::setDAQState(const QString &s){ fDAQState->setText(s); }

const char *TAGDAQ::startComment() const{
  static char cc[512]{};
  strcpy(cc, fStartComment->text().toStdString().data());
  return cc;
} // end member function startComment

const char *TAGDAQ::stopComment() const{
  static char cc[512]{};
  strcpy(cc, fStopComment->text().toStdString().data());
  return cc;
} // end member function stopComment

// return to 'start a new run' status
void TAGDAQ::prepareForANewRun(){
  fStart->setDisabled(false);
  fPause->setDisabled(true);
  fResume->setDisabled(true);
  fStop->setDisabled(true);
  cout << "prepared to start a new Run" << endl;
  fDAQState->setText("DAQ state: <strong>"
    "<span style=\"color:#ff0000\">stopped</span>"
    "</strong>");
} // end member function prepareForANewRun
